﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace AAA.Base.Image
{
    public class ImageProcessor
    {
        private Bitmap _sourceImage;
        private Bitmap _processedImage;
        private byte[,] _bMaskArray;


        public ImageProcessor(Bitmap sourceImage)
        {
            _sourceImage = sourceImage;
            _processedImage = new Bitmap(_sourceImage.Width, _sourceImage.Height);
            _bMaskArray = new byte[sourceImage.Width, sourceImage.Height];
        }

        public Bitmap SourceImage
        {
            get { return _sourceImage; }
//            set { _sourceImage = value; }
        }

        public Bitmap ProcessedImage
        {
            get { return _processedImage; }
//            set { _processedImage = value; }
        }

        public Bitmap CutBackground(Bitmap backgroundImage, int iThreshold)
        {
            return CutBackground(backgroundImage, iThreshold, iThreshold, iThreshold);
        }

        public Bitmap CutBackground(Bitmap backgroundImage, int iThresholdR, int iThresholdG, int iThresholdB)
        {
            return CutBackground(backgroundImage, iThresholdR, iThresholdG, iThresholdB, Color.Black);
        }

        public Bitmap CutBackground(Bitmap backgroundImage, int iThresholdR, int iThresholdG, int iThresholdB, Color cMaskColor)
        {
            if ((backgroundImage.Width != SourceImage.Width) ||
                (backgroundImage.Height != SourceImage.Height))
                return ProcessedImage;

            try
            {
                for (int i = 0; i < backgroundImage.Width; i++)
                    for (int j = 0; j < backgroundImage.Height; j++)
                    {
                        if ((Math.Abs(SourceImage.GetPixel(i, j).R - backgroundImage.GetPixel(i, j).R) < iThresholdR) &&
                            (Math.Abs(SourceImage.GetPixel(i, j).G - backgroundImage.GetPixel(i, j).G) < iThresholdG) &&
                            (Math.Abs(SourceImage.GetPixel(i, j).B - backgroundImage.GetPixel(i, j).B) < iThresholdB))
                        {
                            ProcessedImage.SetPixel(i, j, cMaskColor);
                            _bMaskArray[i, j] = (byte)0;
                        }
                        else
                        {
                            ProcessedImage.SetPixel(i, j, SourceImage.GetPixel(i, j));                            
                            _bMaskArray[i, j] = (byte)1;
                        }
                    }
            }
            catch (Exception e)
            {
            }
            return ProcessedImage;
        }

        public Bitmap MaskByYCbCr(int iCbMin, int iCbMax, int iCrMin, int iCrMax, Color cMaskColor, Color cFillColor)
        {
            YCbCr yCbCr;

            for (int i = 0; i < SourceImage.Width; i++)
                for (int j = 0; j < SourceImage.Height; j++)
                {
                    if (_bMaskArray[i, j] == 0)
                        continue;

                    yCbCr = ImageHelper.RGB2YCbCr(SourceImage.GetPixel(i, j));

                    if ((yCbCr.Cb >= iCbMin) && (yCbCr.Cb <= iCbMax) &&
                       (yCbCr.Cr >= iCrMin) && (yCbCr.Cr <= iCrMax))
                    {
                        ProcessedImage.SetPixel(i, j, cFillColor);
                        _bMaskArray[i, j] = (byte)1;
                    }
                    else
                    {
                        ProcessedImage.SetPixel(i, j, cMaskColor);
                        _bMaskArray[i, j] = (byte)0;
                    }
                }

            return ProcessedImage;
        }

        public Bitmap Erosion(Color cMaskColor, Color cFillColor)
        {            
            int iFillRGB = cFillColor.ToArgb();

            //Left-Upper Pixel
            ProcessedImage.SetPixel(0, 0, cMaskColor);

            //Right-Upper Pixel
            ProcessedImage.SetPixel(SourceImage.Width - 1, 0, cMaskColor);

            //Left-Bottom Pixel
            ProcessedImage.SetPixel(0, SourceImage.Height - 1, cMaskColor);

            //Right-Bottom Pixel
            ProcessedImage.SetPixel(SourceImage.Width - 1, SourceImage.Height - 1, cMaskColor);

            // Horizontal Pixel
            for (int i = 1; i < SourceImage.Width - 1; i++)
            {
                // Top
                ProcessedImage.SetPixel(i, 0, cMaskColor);

                // Bottom
                ProcessedImage.SetPixel(i, SourceImage.Height - 1, cMaskColor);
            }

            // Vertical Pixel
            for (int i = 1; i < SourceImage.Height - 1; i++)
            {
                // Left
                ProcessedImage.SetPixel(0, i, cMaskColor);

                // Right
                ProcessedImage.SetPixel(SourceImage.Width - 1, i, cMaskColor);
            }

            // Center Pixel
            for (int i = 1; i < SourceImage.Width - 1; i++)
                for (int j = 1; j < SourceImage.Height - 1; j++)
                {
                    if (SourceImage.GetPixel(i, j).ToArgb() != iFillRGB)
                    {
                        ProcessedImage.SetPixel(i, j, cMaskColor);
                        continue;
                    }

                    if ((SourceImage.GetPixel(i, j - 1).ToArgb() == iFillRGB) &&
                        (SourceImage.GetPixel(i, j + 1).ToArgb() == iFillRGB) &&
                        (SourceImage.GetPixel(i - 1, j).ToArgb() == iFillRGB) &&
                        (SourceImage.GetPixel(i + 1, j).ToArgb() == iFillRGB))
                        ProcessedImage.SetPixel(i, j, cFillColor);
                    else
                        ProcessedImage.SetPixel(i, j, cMaskColor);
                }

            return ProcessedImage;
        }

        public Bitmap Dilation(Color cMaskColor, Color cFillColor)
        {
            int iFillRGB = cFillColor.ToArgb();

            //Left-Upper Pixel
            if ((SourceImage.GetPixel(1, 0).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(0, 1).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(0, 0).ToArgb() == iFillRGB))
                ProcessedImage.SetPixel(0, 0, cFillColor);
            else
                ProcessedImage.SetPixel(0, 0, cMaskColor);

            //Right-Upper Pixel            
            if ((SourceImage.GetPixel(SourceImage.Width - 2, 0).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(SourceImage.Width - 1, 1).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(SourceImage.Width - 1, 0).ToArgb() == iFillRGB))
                ProcessedImage.SetPixel(SourceImage.Width - 1, 0, cFillColor);
            else
                ProcessedImage.SetPixel(SourceImage.Width - 1, 0, cMaskColor);

            //Left-Bottom Pixel
            if ((SourceImage.GetPixel(0, SourceImage.Height - 2).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(1, SourceImage.Height - 1).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(0, SourceImage.Height - 1).ToArgb() == iFillRGB))
                ProcessedImage.SetPixel(0, SourceImage.Height - 1, cFillColor);
            else
                ProcessedImage.SetPixel(0, SourceImage.Height - 1, cMaskColor);

            //Right-Bottom Pixel
            if ((SourceImage.GetPixel(SourceImage.Width - 2, SourceImage.Height - 1).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(SourceImage.Width - 1, SourceImage.Height - 2).ToArgb() == iFillRGB) ||
                (SourceImage.GetPixel(SourceImage.Width - 1, SourceImage.Height - 1).ToArgb() == iFillRGB))
                ProcessedImage.SetPixel(SourceImage.Width - 1, SourceImage.Height - 1, cFillColor);
            else
                ProcessedImage.SetPixel(SourceImage.Width - 1, SourceImage.Height - 1, cMaskColor);

            // Horizontal Pixel
            for (int i = 1; i < SourceImage.Width - 1; i++)
            {
                // Top
                if (SourceImage.GetPixel(i, 0).ToArgb() == cFillColor.ToArgb())
                {
                    ProcessedImage.SetPixel(i, 0, cFillColor);
                    continue;
                }

                if ((SourceImage.GetPixel(i - 1, 0).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(i + 1, 0).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(i, 1).ToArgb() == iFillRGB))
                    ProcessedImage.SetPixel(i, 0, cFillColor);
                else
                    ProcessedImage.SetPixel(i, 0, cMaskColor);

                // Bottom
                if (SourceImage.GetPixel(i, SourceImage.Height - 1).ToArgb() == iFillRGB)
                {
                    ProcessedImage.SetPixel(i, SourceImage.Height - 1, cFillColor);
                    continue;
                }

                if ((SourceImage.GetPixel(i - 1, SourceImage.Height - 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(i + 1, SourceImage.Height - 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(i, SourceImage.Height - 2) == cFillColor))
                    ProcessedImage.SetPixel(i, SourceImage.Height - 1, cFillColor);
                else
                    ProcessedImage.SetPixel(i, SourceImage.Height - 1, cMaskColor);
            }

            // Vertical Pixel
            for (int i = 1; i < SourceImage.Height - 1; i++)
            {
                // Left
                if (SourceImage.GetPixel(0, i).ToArgb() == iFillRGB)
                {
                    ProcessedImage.SetPixel(0, i, cFillColor);
                    continue;
                }

                if ((SourceImage.GetPixel(0, i - 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(0, i + 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(1, i).ToArgb() == iFillRGB))
                    ProcessedImage.SetPixel(0, i, cFillColor);
                else
                    ProcessedImage.SetPixel(0, i, cMaskColor);

                // Right
                if (SourceImage.GetPixel(SourceImage.Width - 1, i).ToArgb() == iFillRGB)
                {
                    ProcessedImage.SetPixel(SourceImage.Width - 1, i, cFillColor);
                    continue;
                }

                if ((SourceImage.GetPixel(SourceImage.Width - 1, i - 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(SourceImage.Width - 1, i + 1).ToArgb() == iFillRGB) ||
                    (SourceImage.GetPixel(SourceImage.Width - 2, i).ToArgb() == iFillRGB))
                    ProcessedImage.SetPixel(SourceImage.Width - 1, i, cFillColor);
                else
                    ProcessedImage.SetPixel(SourceImage.Width - 1, i, cMaskColor);
            }

            // Center Pixel
            for (int i = 1; i < SourceImage.Width - 1; i++)
                for (int j = 1; j < SourceImage.Height - 1; j++)
                {
                    if (SourceImage.GetPixel(i, j).ToArgb() == iFillRGB)
                    {
                        ProcessedImage.SetPixel(i, j, cFillColor);
                        continue;
                    }

                    if ((SourceImage.GetPixel(i, j - 1).ToArgb() == iFillRGB) ||
                        (SourceImage.GetPixel(i, j + 1).ToArgb() == iFillRGB) ||
                        (SourceImage.GetPixel(i - 1, j).ToArgb() == iFillRGB) ||
                        (SourceImage.GetPixel(i + 1, j).ToArgb() == iFillRGB))
                        ProcessedImage.SetPixel(i, j, cFillColor);
                    else
                        ProcessedImage.SetPixel(i, j, cMaskColor);
                }

            return ProcessedImage;
        }


    }
}
